/*
STL
STL六大组件：容器，算法，迭代器，仿函数，适配器，空间配置器
*容器，置物之所也，将运用最广泛的数据结构实现出来，数组，链表，树，队列，栈，集合，映射表等。
  序列试容器，强调值的排序，每个值都有固定的位置。
  关联式容器：二叉树结构，每个元素之间没有严格物理上的顺序关系。
*算法，问题之解法也，
  质变算法：运算过程中会更改区间内的元素内容。例如拷贝，替换，删除等等。
  非质变算法：运算过程中不会更改区间内的元素内容。例如查找，计数，遍历，寻极值等。
*迭代器，容器和算法之间的粘合剂，提供一种方法，使之能够依序寻访某个容器内所含的各个元素，
而又无需暴漏改容器的内部表示方式。每个容器都有自己的迭代器。迭代器的使用非常类似于指针。
迭代器种类：
    种类	        功能	                      支持运算
  输入迭代器	对数据的只读访问	           只读，支持++、==、！=
  输出迭代器	对数据的只写访问	           只写，支持++
  前向迭代器	读写操作，并能向前推进迭代器	读写，支持++、==、！=
  双向迭代器	读写操作，并能向前和向后操作	读写，支持++、--，
  随机访问迭代器	读写操作，可以以跳跃的方式访问任意数据，功能最强的迭代器	读写，支持++、--、[n]、-n、<、<=、>、>=
常用容器中迭代器的种类为双向迭代器和随机访问迭代器。
*/

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

// vector 存放内置数据元素
void myprint(int val)
{
  cout << val << endl;
}
void func1()
{
  cout << "--------------------------- build in type ---------------------" << endl;
  // 创建 vector 容器对象，并通过模板参数 int 指定容器内存放的变量类型
  vector<int> v;
  v.push_back(10);
  v.push_back(20);
  v.push_back(30);
  v.push_back(40);

  // 每个容器有自己的迭代器，迭代器是用来遍历容器中的元素
  // vector<int>::iterator 拿到 vector<int> 这种容器类型的迭代器
  vector<int>::iterator p_begin = v.begin(); // v.begin()返回迭代器，这个迭代器指向容器中的第一个元素
  vector<int>::iterator p_end = v.end();     // v.end()返回迭代器，这个迭代器指向容器中的最后一个元素的下一个位置

  // 第一种遍历方式
  cout << "The while method iterate..." << endl;
  while (p_begin != p_end)
  {
    myprint(*p_begin);
    p_begin++;
  }

  // 第二种遍历方式
  cout << "The for method iterate..." << endl;
  for (vector<int>::iterator i = v.begin(); i != v.end(); i++)
  {
    myprint(*i);
  }

  // 第三种遍历方式 STL 提供标准遍历算法 algorithm 头文件提供
  cout << "The STL standard algorithm method iterate..." << endl;
  for_each(v.begin(), v.end(), myprint);
}

// vector 自定义数据类型
class Persion
{
public:
  Persion(string name, int age)
  {
    m_name = name;
    m_age = age;
  }

public:
  string m_name;
  int m_age;
};

void func2()
{
  cout << "--------------------------- customize class obj ---------------------" << endl;
  vector<Persion> v;
  v.push_back(Persion("alias", 10));
  v.push_back(Persion("jordan", 50));
  v.push_back(Persion("alex", 20));
  v.push_back(Persion("harden", 30));
  v.push_back(Persion("ivern", 32));

  for (vector<Persion>::iterator it = v.begin(); it != v.end(); it++)
  {
    cout << "name: " << (*it).m_name << " age: " << (*it).m_age << endl;
  }
}

void func3()
{
  cout << "--------------------------- customize pointer obj ---------------------" << endl;
  vector<Persion *> v;
  Persion p1 = Persion("alias", 10);
  Persion p2 = Persion("jordan", 50);
  Persion p3 = Persion("alex", 20);
  Persion p4 = Persion("harden", 30);
  Persion p5 = Persion("ivern", 32);

  v.push_back(&p1);
  v.push_back(&p2);
  v.push_back(&p3);
  v.push_back(&p4);
  v.push_back(&p5);

  for (vector<Persion *>::iterator it = v.begin(); it != v.end(); it++)
  {
    cout << "name: " << (*it)->m_name << " age: " << (*it)->m_age << endl;
  }
}

// vector 容器嵌套容器
void func4()
{
  cout << "--------------------------- vector nested vector ---------------------" << endl;
  vector<vector<int>> v;

  vector<int> v1;
  vector<int> v2;
  vector<int> v3;
  vector<int> v4;
  for (int i = 0; i < 4; i++)
  {
    v1.push_back(i);
    v2.push_back(i + 10);
    v3.push_back(i + 100);
    v4.push_back(i + 1000);
  }

  v.push_back(v1);
  v.push_back(v2);
  v.push_back(v3);
  v.push_back(v4);

  for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
  {
    for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
      cout << *vit << " ";
    cout << endl;
  }
}

int main()
{
  // vector 内建数据类型
  func1();
  func2();
  func3();
  func4();

  return 0;
}